package com.zlsy.secondtime.deadlock;

import java.util.Random;

/**
 * @author zhouliang
 * @date 2020/6/18 19:34
 */
public class MultiTransferMoney implements Runnable {
    /**
     * 账户数量
     */
    private static final int NUM_ACCOUNTS = 500;
    /**
     * 每个账户的初始钱
     */
    private static final int NUM_MONEY = 1000;
    /**
     * 每个线程产生的交易数量
     */
    private static final int NUM_TRANSFER = 100000;
    /**
     * 随机数定义
     */
    private static final Random RANDOM = new Random();

    public static void main(String[] args) {
        //初始化500个账户
        MultiTransferMoneyAccount[] accounts = new MultiTransferMoneyAccount[NUM_ACCOUNTS];
        //往每笔账户里面放入一笔钱
        for (int i = 0; i < accounts.length; i++) {
            accounts[i] = new MultiTransferMoneyAccount(NUM_MONEY);
        }

        MultiTransferMoney r = new MultiTransferMoney(accounts);
        for (int i = 0; i < 20; i++) {
            Thread thread = new Thread(r);
            thread.start();
        }
    }

    /**
     * 转账
     *
     * @param from   来源账户
     * @param to     转过去的账户
     * @param amount 转账金额
     */
    private static void transferMoney(MultiTransferMoneyAccount from, MultiTransferMoneyAccount to, int amount) {
        synchronized (from) {
            synchronized (to) {
                if (from.balance - amount < 0) {
                    System.out.println("余额不足！");
                }
                from.balance -= amount;
                to.balance += amount;
                System.out.println("转账完成！");
            }
        }
    }

    private MultiTransferMoneyAccount[] accounts;

    public MultiTransferMoney(MultiTransferMoneyAccount[] accounts) {
        this.accounts = accounts;
    }

    @Override
    public void run() {
        for (int i = 0; i < NUM_TRANSFER; i++) {
            int fromIndex = RANDOM.nextInt(NUM_ACCOUNTS);
            int toIndex = RANDOM.nextInt(NUM_ACCOUNTS);
            int amount = RANDOM.nextInt(NUM_MONEY);
            transferMoney(accounts[fromIndex], accounts[toIndex], amount);
        }
    }


    /**
     * 多人转账的账户
     */
    static class MultiTransferMoneyAccount {
        private int balance;

        public MultiTransferMoneyAccount(int balance) {
            this.balance = balance;
        }
    }
}
